package com.hmdp.utils;

import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;

@Component
public class RedisIdWorker {
    // 2022-01-01 00:00:00 的 Unix 时间戳（以秒为单位）
    private static final long BEGIN_TIMESTAMP = 1640995200L;
    // serial number bits
    private static final int COUNT_BITS = 32;

    private StringRedisTemplate stringRedisTemplate;

    public RedisIdWorker(StringRedisTemplate stringRedisTemplate) {
        this.stringRedisTemplate = stringRedisTemplate;
    }
    public long nextId(String keyPrefix) {
        // 获取当前时间
        LocalDateTime now = LocalDateTime.now();
        
        // 将当前时间转换为基于 UTC 时区的 Unix 时间戳（以秒为单位）
        long nowSecond = now.toEpochSecond(ZoneOffset.UTC);
        
        // 计算相对于自定义起始时间的时间差（单位：秒）
        // BEGIN_TIMESTAMP 是 2022-01-01 00:00:00 的时间戳，用于减小生成的时间戳数值大小
        long timestamp = nowSecond - BEGIN_TIMESTAMP;
        
        // 创建序列号部分：使用当天日期作为 Redis 自增键的一部分
        String date = now.format(DateTimeFormatter.ofPattern("yyyy:MM:dd"));
        
        // 在 Redis 中根据 keyPrefix 和日期进行自增操作
        // 每天会重置一次自增计数器，确保 ID 的唯一性
        Long countObj = stringRedisTemplate.opsForValue().increment("icr:" + keyPrefix + ":" + date);
        long count = (countObj != null) ? countObj : 0;
        
        // 最终生成一个长整型 ID：
        // 1. 将前面计算出的时间戳左移 COUNT_BITS 位（32位），腾出空间给序列号
        // 2. 使用按位或运算符 '|' 合并时间戳和序列号
        // 这样最终的 ID 前面一部分是时间戳，后面一部分是当日的自增序号
        return timestamp << COUNT_BITS | count;
    }
}
